/**
 * Copyright(c) KuGou-Inc.All Rights Reserved.
 */
package top.suven.base.http.Interceptor;

import top.suven.base.core.redis.RedisClusterServer;
import top.suven.base.core.redis.RedisConstants;
import top.suven.base.core.redis.RedisKeys;
import top.suven.base.http.config.HttpServiceConfig;
import top.suven.base.http.config.LoginValidType;
import top.suven.base.http.enums.SysProjectEmumType;
import top.suven.base.http.message.ParamMessage;
import top.suven.base.http.message.RequestMessage;
import top.suven.base.http.processor.url.URLCommand;
import top.suven.base.util.utilize.JsonUtils;
import top.suven.base.common.platform.FingerJMSMessage;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * <pre>
 * 程序的中文名称。
 * </pre>
 * @author suven.wang@kugou.net
 * @version 1.00.00
 * <pre>
 * 修改记录
 *    修改后版本:     修改人：  修改日期:     修改内容:
 * </pre>
 */
@Component("userTokenValidator")
public class UserTokenValidator {
	private Logger logger = LoggerFactory.getLogger(getClass());
	private final String URL_VERIFY_TOKEN = "/top/suven/base/authorize/checkToken";


	@Autowired
	private RedisClusterServer redisClusterServer;

	@Autowired
	private HttpServiceConfig httpServiceConfig;

	private LoadingCache<Long,Boolean> cache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.MINUTES) .build(new CacheLoader<Long,Boolean>() {
		@Override
		public Boolean load(Long passportId) {
			boolean isVerify = true;
			try {
				isVerify = passportVerify();
			}catch (Exception e){
				logger.error("",e);
			}
			return isVerify;
		}
	});

	private LoadingCache<String,Boolean> projectCache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.MINUTES) .build(new CacheLoader<String,Boolean>() {
		@Override
		public Boolean load(String serverName) {
			boolean isVerify = false;
			try {
				isVerify = projectVerify();
			}catch (Exception e){
				logger.error("",e);
			}
			return isVerify;
		}
	});

	public Boolean passportVerify() {
		boolean isSessionSuccess = true;//session验证是否成功
		boolean isTokenSuccess = true;//token验证是否成功
		RequestMessage requestMessage = ParamMessage.getRequestMessage();
		if(LoginValidType.isToken(httpServiceConfig.getValidType())) {
			String userId = redisClusterServer.get(RedisKeys.ACCESS_TOKEN + requestMessage.getAccessToken());
			logger.info("param accessToken={},redis accessToken={}", requestMessage.getAccessToken(), userId);
			if (StringUtils.isNotBlank(userId) && userId.equals(String.valueOf(requestMessage.getUserId()))) {
				redisClusterServer.expire(RedisKeys.ACCESS_TOKEN + requestMessage.getAccessToken(), RedisConstants.ONE_DAY);
			}else {
				isTokenSuccess = false;
			}
		}
		if(LoginValidType.isSession(httpServiceConfig.getValidType())) {
			String  fingerSession = redisClusterServer.get(String.valueOf(requestMessage.getUserId()));
			String sessionId = null;
			if(StringUtils.isNotBlank(fingerSession)){
				FingerJMSMessage fingerJMSMessage = JsonUtils.readValue(fingerSession,FingerJMSMessage.class);
				sessionId = fingerJMSMessage.getSessionId();
			}
			logger.info("param sessionId={},redis sessionId={}", requestMessage.getSessionId(), sessionId);


			if (StringUtils.isNotBlank(fingerSession) && sessionId.equals(String.valueOf(requestMessage.getSessionId()))) {
				redisClusterServer.expire(String.valueOf(requestMessage.getSessionId()), RedisConstants.ONE_DAY);
			}else {
				isSessionSuccess = false;
			}
		}
		return isSessionSuccess&&isTokenSuccess;
	}

	public boolean projectVerify() {
		String url = ParamMessage.getRequestRemote().getUrl();
		if(StringUtils.isNotBlank(url) && (url.indexOf(URLCommand.auth_start_maintain_module) != -1 ||
				url.indexOf(URLCommand.auth_get_maintain_module) != -1)){
			return false;
		}
		String serverName = ParamMessage.getRequestRemote().getModule();
		List<String> projectNameList = Arrays.stream(SysProjectEmumType.values()).filter(e->e.getProjectName().endsWith(serverName.toUpperCase())).
				map(e->e.getProjectName()).collect(Collectors.toList());
		if(projectNameList == null || projectNameList.isEmpty()){
			return false;
		}
		if(this.isMaintainModule(projectNameList.get(0))){
			return true;
		}
		return false;
	}
	/**
	 * @Title: 验证模块是否维护模式
	 * @Description:
	 * @param
	 * @return
	 * @throw
	 * @author lixiangling
	 * @date 2018/7/9 19:18
	 *  --------------------------------------------------------
	 *  modifyer    modifyTime                 comment
	 *
	 *  --------------------------------------------------------
	 */
	private boolean isMaintainModule(String serverProjectName) {
		String projectNames = redisClusterServer.get(RedisKeys.OAUTH_MAINTAIN + "ALL");
		List<String> projectNameList = new ArrayList<>();
		if(!StringUtils.isBlank(projectNames)) {
			projectNameList.addAll(Arrays.asList(StringUtils.split(projectNames, ",")));
		}
		logger.info("origin serverNames={},request serverName={}",projectNames, serverProjectName);
		if(!projectNameList.isEmpty()&&projectNameList.contains(serverProjectName)){
			return true;
		}
		return false;
	}


	/**
	 * @return 返回 cache。
	 */
	public LoadingCache<Long, Boolean> getCache() {
		return cache;
	}

	public LoadingCache<String, Boolean> getProjectCache() {
		return projectCache;
	}

	public static  void main(String[] arg) throws Exception{
		UserTokenValidator us = new UserTokenValidator();
		RequestMessage tp = new RequestMessage();
		us.passportVerify();
	}
}
